#!/usr/bin/env python
# encoding: utf-8
import wx
import random
from testMidiNote import Midi
import gammeDict

#A faire:
#        -Implementation de l'angle changeante de la balle...
#        -Completer les differentes gamme pour avoir plusieurs difficulte.

#        -Faire une page des preferences.
#        -Pouvoir voir la liste des port midi disponible et de pouvoir le changer.
#        -Pouvoir changer l'octave depuis les preferences.
#        -Changer les gammes, une liste de gamme differente, pouvoir personnaliser ta liste...

#        -Faire une classe Joueur ?

#        -Bloquer a une dimension minimum. -> Mettre a plein ecran ?
#        -La balle doit suivre lorsqu'on redimensionne la fenetre.
#        -S'arrenger pour que les barres suivent le redimensionnement et de faire en sorte que les sauts des barre suivre les nouvelles dimension.
#        -Bug: Quand on resize, la balle ne suis plus et cela cause de nombreux bugs.
#        -Porté sur windows. La fenêtre ne s'update pas, elle ne fait que dessiner.
 
class Surface(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
        
        self.p1Pos = 320
        self.scoreP1= "00"
        self.levelP1= 0
        self.octaveP1=2
        self.p2Pos= 320
        self.scoreP2= "00"
        self.levelP2= 0
        self.octaveP2=5
        
        self.ballPos = [500, 350]
        
        # A 0 de y, x prend la valeur de 4, et a 9 de y x prend la valeur de 1.5.
        # Angle
        self.y= random.uniform(0,9)
        # Vitesse
        self.x= 1.5
        
        #Savoir a qui le tour de frapper la balle.
        self.bounceP1=False
        
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
        
        self.colliP1= wx.Rect(20, self.p1Pos,20,95)
        self.colliP1_Haut=wx.Rect(5, self.p1Pos-20, 30, 20)
        self.colliP1_Bas=wx.Rect(5, self.p1Pos+85, 30, 20)
        self.colliP2= wx.Rect(960, self.p2Pos,20,95)
        self.colliP2_Haut=wx.Rect(960, self.p2Pos-20, 30, 20)
        self.colliP2_Bas=wx.Rect(960, self.p2Pos+85, 30, 20)
        
        self.joue= False
        self.midi= Midi(self)
    
    def OnSize(self, evt):
        self.Refresh()
    
    def checkOnSize(self):
        w,h= self.GetSize()
        if self.p1Pos >= h-120:
            self.p1Pos= h-120
        if self.p2Pos >= h-120:
            self.p2Pos= h-120
    
    def OnKeyDown(self, evt):
        keycode = evt.GetKeyCode()
        
         #Joueur 1, Pour les tests.
        if keycode == ord('W') or keycode == ord('w'):
            self.moveP1Up()
        elif keycode == ord('S') or keycode == ord('s'):
            self.moveP1Down()
        
        #Joueur 2, Pour les tests.
        if keycode == wx.WXK_UP:
            self.moveP2Up()
        elif keycode == wx.WXK_DOWN:
            self.moveP2Down()
        
        #Marche/Arret
        if keycode == wx.WXK_SPACE:
            if not self.joue:
                self.midi.go()
                self.joue=True
            else:
                self.midi.arret()
                self.joue=False
        
        self.Refresh()
    
    def OnPaint(self, e):
        w,h= self.GetSize()
        dc= wx.AutoBufferedPaintDC(self)
        #Dessine l'interface
        dc.SetPen(wx.Pen("#FFFFFF", 4, wx.SHORT_DASH))
        dc.DrawLine(w/2,80,w/2,h-25)
        dc.SetPen(wx.Pen("#FFFFFF", 4, wx.SOLID))
        dc.DrawLine(0,80,w,80)
        dc.DrawLine(0,h-25,w,h-25)
        
        dc.SetFont(wx.Font(48, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
        dc.SetTextForeground("#FFFFFF")
        #Ecrit les scores
        dc.DrawLabel(self.scoreP1, (10,10, 50, 50))
        dc.DrawLabel(self.scoreP2, (w-70, 10, 50, 50))
        #Ecrit le level rendu
        if self.levelP1 < len(gammeDict.nom):
            dc.DrawLabel(gammeDict.nom[self.levelP1], (150, 10, 50, 50))
        if self.levelP2 < len(gammeDict.nom):
            dc.DrawLabel(gammeDict.nom[self.levelP2], (w-300, 10, 50, 50))
        
        ### Dessine la balle...
        dc.DrawCircle(self.ballPos[0], self.ballPos[1], radius=10)
        
        # Dessine les rectangles
        dc.DrawRectangle(5, self.p1Pos,15,85)
        dc.DrawRectangle(w-25, self.p2Pos,15,85)
        
        dc.SetPen(wx.Pen("#FFFF00", 4, wx.SOLID))
        #dc.DrawRectangle(5, self.p1Pos+85, 30, 20)
        #dc.DrawRectangle(w-35, self.p2Pos-5,30,95)
        
        self.colliP1.Set(5, self.p1Pos-5, 30,95)
        self.colliP1_Haut.Set(5, self.p1Pos-15, 30, 20)
        self.colliP1_Bas.Set(5, self.p1Pos+80, 30, 20)
        
        self.colliP2.Set(w-38, self.p2Pos-5,30,95)
        self.colliP2_Haut.Set(w-38, self.p2Pos-15, 30, 20)
        self.colliP2_Bas.Set(w-38, self.p2Pos+80, 30, 20)
        self.checkOnSize()
    
    #Get/Set Level P1/P2
    def setLevelP1(self, level):
        self.levelP1=level
    
    def incLevelP1(self, level):
        self.levelP1+=level
    
    def getLevelP1(self):
        return self.levelP1
    
    def setLevelP2(self, level):
        self.levelP2=level
    
    def incLevelP2(self, level):
        self.levelP2+=level

    def getLevelP2(self):
        return self.levelP2
    
    #Get/Set Ocatve P1/P2
    def setOctaveP1(self, octave):
        self.octaveP1=octave
    
    def getOctaveP1(self):
        return self.octaveP1
    
    def setOctaveP2(self, octave):
        self.octaveP2=octave

    def getOctaveP2(self):
        return self.octaveP2
    
    #Get/Set Score P1/P2
    def getScoreP1(self):
        return int(self.scoreP1)
    
    def setScoreP1(self, score):
        tempScore= int(self.scoreP1)
        tempScore = score
        self.scoreP1="%02d"%tempScore
        wx.CallAfter(self.Refresh)
    
    def incScoreP1(self, score):
        tempScore= int(self.scoreP1)
        tempScore += score
        self.scoreP1="%02d"%tempScore
        wx.CallAfter(self.Refresh)
    
    def getScoreP2(self):
       return int(self.scoreP2)
    
    def setScoreP2(self, score):
        tempScore= int(self.scoreP2)
        tempScore = score
        self.scoreP2="%02d"%tempScore
        wx.CallAfter(self.Refresh)
    
    def incScoreP2(self, score):
        tempScore= int(self.scoreP2)
        tempScore += score
        self.scoreP2="%02d"%tempScore
        wx.CallAfter(self.Refresh)
    
    #Move P1/P2
    def moveP1Up(self):
        w,h= self.GetSize()
        topMax= 90
        if self.p1Pos>=topMax:
            self.p1Pos -= 33
        wx.CallAfter(self.Refresh)
    
    def moveP1Down(self):
        w,h= self.GetSize()
        bottomMax= h-120
        if self.p1Pos<=bottomMax:
            self.p1Pos += 33
        wx.CallAfter(self.Refresh)
    
    def moveP2Up(self):
        w,h= self.GetSize()
        topMax= 90
        if self.p2Pos>=topMax:
            self.p2Pos -= 33
        wx.CallAfter(self.Refresh)
    
    def moveP2Down(self):
        w,h= self.GetSize()
        bottomMax= h-120
        if self.p2Pos<=bottomMax:
            self.p2Pos += 33
        wx.CallAfter(self.Refresh)
    
    #Methodes de la balle.
    def newBall(self):
        w,h= self.GetSize()
        self.ballPos= [w/2, (h+40)/2]
        self.x= -self.x
        self.y= random.uniform(0,9)
    
    def moveBall(self):
        w,h= self.GetSize()
        self.ballPos[0]-=self.x
        self.ballPos[1]+=self.y
        #Collision avec le haut et bas
        if self.ballPos[1]<=90 or self.ballPos[1]>=h-40:
            self.y= -self.y
        
        #Collision avec les barres
        #if self.ballPos[0]<=33 and self.ballPos[1]>=self.p1Pos and self.ballPos[1]<=self.p1Pos+85:
         #   self.x= -self.x
        #if self.ballPos[0]>=w-40 and self.ballPos[1]>=self.p2Pos and self.ballPos[1]<=self.p2Pos+85:
         #   self.x= -self.x
        
        if self.colliP1.ContainsXY(self.ballPos[0], self.ballPos[1]) and not self.bounceP1:
            self.x= -self.x
            self.bounceP1=True
        if self.colliP1_Haut.ContainsXY(self.ballPos[0], self.ballPos[1]) and not self.bounceP1:
            self.x= -self.x
            self.y= -self.y
            self.bounceP1=True
        if self.colliP1_Bas.ContainsXY(self.ballPos[0], self.ballPos[1]) and not self.bounceP1:
            self.x= -self.x
            self.y= -self.y
            self.bounceP1=True
        if self.colliP2_Haut.ContainsXY(self.ballPos[0], self.ballPos[1]) and self.bounceP1:
            self.x= -self.x
            self.y= -self.y
            self.bounceP1=False
        if self.colliP2_Bas.ContainsXY(self.ballPos[0], self.ballPos[1]) and self.bounceP1:
            self.x= -self.x
            self.y= -self.y
            self.bounceP1=False
        if self.colliP2.ContainsXY(self.ballPos[0], self.ballPos[1]) and self.bounceP1:
            self.x= -self.x
            self.bounceP1=False
        
        #crash
        #Joueur 2
        if self.ballPos[0]<=5:
            self.incScoreP2(1)
            self.newBall()
            self.bounceP1=True
            #Changement de Gamme:
            if self.getScoreP2()!= 0 and self.getScoreP2()%5==0:
                self.incLevelP2(1)
                self.midi.arret()
                self.midi.newGamme("P2")
                self.p2Pos= 320
                self.joue=False
        #Joueur 1
        if self.ballPos[0]>=w-5:
            self.incScoreP1(1)
            self.newBall()
            self.bounceP1=False
            #Changement de Gamme:
            if self.getScoreP1()!= 0 and self.getScoreP1()%5==0:
                self.incLevelP1(1)
                self.midi.arret()
                self.midi.newGamme("P1")
                self.p1Pos= 320
                self.joue=False
        wx.CallAfter(self.Refresh)
    
        




class MyFrame(wx.Frame):
    def __init__(self, parent, title, pos, size):
        wx.Frame.__init__(self, parent, id=-1, title=title, pos=pos, size=size)
        menubar= wx.MenuBar()
        fileMenu= wx.Menu()
        fileMenu.AppendSeparator()
        fileMenu.Append(wx.ID_EXIT, "Quit\tCtrl+Q")
        menubar.Append(fileMenu, "File")
        self.SetMenuBar(menubar)
        
        self.Bind(wx.EVT_MENU, self.onQuit, id=wx.ID_EXIT)
        self.Bind(wx.EVT_CLOSE, self.onQuit)
        
        self.panel=wx.Panel(self)
        self.box= wx.BoxSizer(wx.VERTICAL)
        self.panel.SetBackgroundColour("#000000")
        self.size= self.GetSize()
        self.font= wx.Font(48, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
        
        self.surface= Surface(self.panel)
        self.box.Add(self.surface, 1, wx.EXPAND|wx.ALL, 1)
        self.panel.SetSizer(self.box)
        self.surface.SetFocus() # donne le focus a la surface, pour la reception des keyevents
        self.Show()
    
    def onQuit(self, evt):
        self.surface.midi.stop()
        self.Destroy()
    

    
app = wx.App(False)

mainFrame = MyFrame(None, title="PongKey", pos=(100,23), size=(1000,700))

app.MainLoop()
